package cn.itrip.auth.service;

import cn.itrip.auth.exception.RedisException;
import cn.itrip.auth.exception.TokenProtectedException;
import cn.itrip.beans.pojo.ItripUser;
import cn.itrip.beans.vo.ItripTokenVO;
import cn.itrip.common.MD5;
import cn.itrip.common.RedisAPI;
import cn.itrip.common.UserAgentUtil;
import cn.itrip.mapper.itripUser.ItripUserMapper;
import com.alibaba.fastjson.JSON;
import com.sun.org.apache.bcel.internal.generic.RETURN;
import cz.mallat.uasparser.UserAgentInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * @ClassName TokenServiceImpl
 * @Description TODO
 * @Author yaozhaobao
 * @Date 2020/12/14 14:58
 * @Version 1.0
 **/
@Service
public class TokenServiceImpl implements  TokenService{


    @Autowired
    RedisAPI redisAPI;
    @Autowired
    ItripUserMapper itripUserMapper;

    /**
     * token:PC-md5(userCode)-id-系统时间-agent
     * @param agent
     * @param itripUser
     * @return
     */
    @Override
    public String genarateToken(String agent, ItripUser itripUser) throws Exception {
        StringBuilder builder =new StringBuilder("token:");

        try {
            UserAgentInfo userAgentInfo = UserAgentUtil.getUasParser().parse(agent);
            String deviceType=userAgentInfo.getDeviceType();
            if(deviceType.equals("Personal Computer")){
                //PC端
                builder.append("PC-");
            }else if(deviceType.equals(UserAgentInfo.UNKNOWN)){
                if(UserAgentUtil.CheckAgent(agent)){
                    //移动端
                    builder.append("MOBILE-");
                }else{
                    //PC
                    builder.append("PC-");
                }
            }else{
                builder.append("PC-");
            }

            ItripUser itripUser1=itripUserMapper.getItripUserByuserCode(itripUser.getUserCode());
            builder.append(MD5.getMd5(itripUser.getUserCode(),32));
            builder.append("-"+itripUser1.getId()+"-");
            builder.append(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())+"-");
            builder.append(MD5.getMd5(agent,6));

        } catch (IOException e) {
            e.printStackTrace();
        }


        return builder.toString();
    }

    @Override
    public String genarateToken2(String msagent, ItripUser itripUser) throws Exception {
        ItripUser itripUser1=itripUserMapper.getItripUserByuserCode(itripUser.getUserCode());
        StringBuilder builder =new StringBuilder("token:");
        builder.append("PC-");
        builder.append(MD5.getMd5(itripUser.getUserCode(),32));
        builder.append("-"+itripUser1.getId()+"-");
        builder.append(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())+"-");
        builder.append(msagent);
        return builder.toString();
    }

    @Override
    public boolean saveToken(String tokenkey, ItripUser itripUser) throws  Exception{
        //pc端则设置redis过期时间2小时
        if(tokenkey.startsWith("token:PC-")){
         return   redisAPI.set(tokenkey,TOKEN_TIMEOUT, JSON.toJSONString(itripUser));
        }

        //移动端不过时
        return   redisAPI.set(tokenkey,JSON.toJSONString(itripUser));
    }


    @Override
    public boolean validateToken(String token, String agent) {
        //第一次校验：判断token是否存在redis
        if(!redisAPI.exist(token.trim())){
            return false;
        }else{
            //第二次校验：防止token被别人截取然后发送的请求，agent
            //token:PC-01d7f40760960e7bd9443513f22ab9af-31-20201214164312-0b433a
            String code =token.split("-")[4];
            String code2=MD5.getMd5(agent,6);
            if(code.equals(code2)){
                return true;
            }else{
                return false;
            }
        }
    }

    @Override
    public void deleteToken(String token) throws  Exception {
        redisAPI.delete(token);
    }


    /**
     * 用户第一次请求：3:00   token----->2小时
     * 用户发送请求接口： 4:59 浏览网页，触发token置换,没来得及吧token返回到前端
     * 用户发送请求其他接口：5:00 携带还是旧的token访问系统，掉线了
     *
     * 解决：
     *   置换token的时候，给旧token延长2分钟
     *
     *   token:PC-01d7f40760960e7bd9443513f22ab9af-31-20201215143613-0b433a
     * @param token
     * @param agent
     */
    @Override
    public ItripTokenVO refreshToken(String token, String agent) throws TokenProtectedException, ParseException, RedisException {
        //判断是否到达token置换的时间,是否在保护期,token还能继续用
        String time =token.split("-")[3];
        try {
            Date date =new SimpleDateFormat("yyyyMMddHHmmss").parse(time);
            long t= Calendar.getInstance().getTimeInMillis()- date.getTime();
            if(t<(TokenService.TOKEN_TIMEOUT-TokenService.PROTECT_TIME)*1000){
                //保护期
                throw new TokenProtectedException("token还在保护器,无法置换token");

            }

            //生成新的token
            String userjson =redisAPI.get(token);
            ItripUser user =JSON.parseObject(userjson,ItripUser.class);
            String  newtoken= this.genarateToken(agent,user);
            //新旧token数据移交
            this.saveToken(newtoken,user);
            //旧的token续命2分钟
            redisAPI.set(token,TokenService.DELAY_TIME,userjson);

            //返回token
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
            Date newsdate = simpleDateFormat.parse(newtoken.split("-")[3]);
            long gen= newsdate.getTime();
            long expire=newsdate.getTime()+TokenService.TOKEN_TIMEOUT;
            ItripTokenVO itripTokenVO = new ItripTokenVO(token,expire,gen);
            return itripTokenVO;
        } catch (ParseException e) {
            throw  e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RedisException(e.getMessage());
        }
    }


}
